import Image
import os
import math
import abstract_engine
from ProcessingError import *
import logging


class PILEngine(object, abstract_engine.AbstractEngine):

    def __init__(self):
	self.log = logging.getLogger("pyips." + __name__)
	self.log.setLevel(logging.INFO)
    
    def read_image(self, image_name):
	if not os.path.exists(image_name):
	    raise ProcessingError(image_name, "There are no such file as %s" % image_name)
	image = Image.open(image_name)
	self.log.info('Image readed')
	return image

    def save_image(self, image, name_to_save, type_to_save):
	image.size = int(image.size[0]), int(image.size[1])
	if not type_to_save:
	    type_to_save = image.format
	try:
	    image.save(name_to_save, type_to_save)
	except IOError, e:
	    raise ProcessingError(name_to_save, e)
	image = None
	self.log.info('Image saved to %s' % name_to_save)


    def crop_image(self, image, width, height, crop_type):
	original_width, original_height = image.size
	offset_x = max(0, math.floor(float(original_width - width) / 2))
	offset_y = max(0, math.floor(float(original_height - height) / 2))
	self.log.info("Croping image with size %dx%d" % (original_width, original_height))
	if crop_type == "top":
	    offset_y = 0
	elif crop_type == "center":
	    pass
	    
	cropped_width = min(original_width, offset_x + width)
	cropped_height = min(original_height, offset_y + height)
	
	if offset_x == 0 and offset_y == 0\
	    and cropped_width == original_width and cropped_height == original_height:
	    return image
	    
	self.log.info('Cropping center from %d;%d to %d;%d' % (offset_x, offset_y, cropped_width, cropped_height))
	
	image = image.crop((offset_x, offset_y, offset_x + width, offset_y + height))
	return image
	

    def scale_image(self, image, width, height, crop_type=None, is_scale_up_allowed=False):

	original_width, original_height = image.size
	
	x_factor = float(width) / original_width
	y_factor = float(height) / original_height

	if crop_type == None:
	    factor = min(x_factor, y_factor)
	    if factor > 1 and not is_scale_up_allowed:
		pass
	    else:
                if x_factor == factor:
                    resize_width = width
                    resize_height = int(math.floor(factor * original_height))
                else:
                    resize_width = int(math.floor(factor * original_width))
    		    resize_height = height
		self.log.info('Scaling without resizing to %dx%d' % (resize_width, resize_height))
		image = image.resize((resize_width, resize_height), Image.ANTIALIAS)
	else:
	    factor = max(x_factor, y_factor)

	    if factor > 1 and not is_scale_up_allowed:
		pass
	    else:
                if x_factor == factor:
                    resize_width = width
                    resize_height = int(math.floor(factor * original_height))
                else:
                    resize_width = int(math.floor(factor * original_width))
    		    resize_height = height
		self.log.info('Scaling with crop to %dx%d' % (resize_width, resize_height))
		image = image.resize((resize_width, resize_height), Image.ANTIALIAS)

	    image = self.crop_image(image, width, height, crop_type)	    
	return image

